﻿/**********************************************************/
/*                Code by: Sam Wronski                    */
/*             email: runewake2@gmail.com                 */
/* Distributed under the Microsoft Public License (Ms-PL) */
/**********************************************************/
/*     https://gamejolttrophies.codeplex.com/license      */
/**********************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Security.Cryptography;

namespace GameJoltAPI
{
    /// <summary>
    /// The Settings Class contains general data that the API will use periodicly.
    /// You should set the GameID, Username and Token in this before using the rest
    /// of the API.
    /// </summary>
    public class Settings
    {
        private static string _gid;     //The games ID
        private static string _key;     //The games private key
        private static string _user;    //The users name
        private static string _token;   //The users token
        private static bool _validated; //This is true if the current User/Token pair has been authenticated, it is false otherwise

        public static event PropertyChangedEventHandler GameIDChanged;

        /// <summary>
        /// The Game ID is a unique identified that is used to Identify which game is using the API
        /// This ID may be found on your Game Dashboard under "Manage Achievements"
        /// </summary>
        public static string GameID { get { return _gid; }
            set {
                if (_gid != value)
                {
                    _gid = value;
                    if (GameIDChanged != null)
                        GameIDChanged(_gid, new PropertyChangedEventArgs("GameID"));
                }
            }
        }

        public static event PropertyChangedEventHandler GameKeyChanged;

        /// <summary>
        /// The Game Key is a private key found with your Game ID.
        /// It is used for generating the signitures the API uses to validate your calls.
        /// It is important that you NEVER share your Game Key with anyone as sharing
        /// it would allow them to hack your game.
        /// </summary>
        public static string GameKey
        {
            get { return _key; }
            set
            {
                if (_key != value)
                {
                    _key = value;
                    if (GameKeyChanged != null)
                        GameKeyChanged(_gid, new PropertyChangedEventArgs("GameKey"));
                }
            }
        }

        public static event PropertyChangedEventHandler UsernameChanged;

        /// <summary>
        /// The User's Username is used to uniquely identify a user and enable them
        /// to login to the API.
        /// This is required to validate the User's Credentials and use the API
        /// </summary>
        public static string Username
        {
            get { return _user; }
            set
            {
                if (_user != value)
                {
                    _user = value;
                    if (UsernameChanged != null)
                        UsernameChanged(_gid, new PropertyChangedEventArgs("Username"));
                    if (_validated)
                    {
                        _validated = false;
                        UserValidationChanged(null, new PropertyChangedEventArgs("Validated"));
                    }
                }
            }
        }

        public static event PropertyChangedEventHandler TokenChanged;

        /// <summary>
        /// The User's Token is an identifier that enables them to login to the API
        /// This is required to validate the User's Credentials and use the API
        /// </summary>
        public static string Token
        {
            get { return _token; }
            set
            {
                if (_token != value)
                {
                    _token = value;
                    if (TokenChanged != null)
                        TokenChanged(_gid, new PropertyChangedEventArgs("Token"));
                    if (_validated)
                    {
                        _validated = false;
                        UserValidationChanged(null, new PropertyChangedEventArgs("Validated"));
                    }
                }
            }
        }

        /// <summary>
        /// This event is called when the user's credentials are validated
        /// </summary>
        public static event EventHandler OnValidatedUser;

        /// <summary>
        /// This event is called whenever the User's validation changes
        /// </summary>
        public static event PropertyChangedEventHandler UserValidationChanged;

        /// <summary>
        /// Gets if the current Username/Token pair is valid or not.
        /// Other functions of the Game Jolt API will throw exceptions if this is not true.
        /// </summary>
        public static bool Validated
        {
            get { return _validated; }
        }

        /// <summary>
        /// This property is not used by the API itself and is intended as a helper variable only
        /// It will return true when all necassary values exist and false otherwise.
        /// </summary>
        public static bool AllowAPICalls
        {
            get
            {
                return _gid != null && _key != null && Validated;
            }
        }

        public static void SetUser(string name, string token, bool authenticate = true)
        {
            _validated = false;
            Username = name;
            Token = token;
            if (authenticate)
            {
                UserClient uc = new UserClient();
                uc.OnAuthenticationComplete += EAuthSuccess;
                uc.OnAuthenticationError    += EAuthFailure;
                uc.AuthenticateUser();
            }
        }
        private static void EAuthSuccess(object sender, EventArgs e) { _validated = true; }
        private static void EAuthFailure(object sender, EventArgs e) { _validated = false; }

        /// <summary>
        /// Generates a Signiture for a request to the specified location
        /// </summary>
        /// <param name="url">Where the call is going</param>
        /// <returns>the signiture</returns>
        public static string Signiture(string url)
        {
            MD5 m = MD5.Create();
            byte[] data = m.ComputeHash(Encoding.UTF8.GetBytes(url+GameKey)); //Slap a gamekey on their and encode hash

            StringBuilder sbuild = new StringBuilder();

            for (int i = 0; i < data.Length; ++i)
                sbuild.Append(data[i].ToString("x2"));

            return sbuild.ToString();
        }
    }
}
